﻿/*﻿
SINACOR - BMF&Bovespa
Arquivo: DistribuicaoNegocio.cs
Criado em: 20-jul-2010 11:59:16
Arquiteto Responsvel: p-dmartinelli
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using Sinacor.Infra.Service.Common;
using Sinacor.Infra.Service.ExceptionHandling;
using Sinacor.Infra.Service.Validation;
using Sinacor.Servico.Bovespa.Alocacao.BusinessEntity;
using Sinacor.Infra.Service.Security.Authorization;
using Sinacor.Infra.Service.Validation.BusinessRules;
using Sinacor.Servico.Bovespa.Ordens.BusinessEntity;
using Sinacor.Infra.Common.Exceptions;
using Sinacor.Infra.Common.Validation;


namespace Sinacor.Servico.Bovespa.Alocacao.BusinessLogic
{
    public class DistribuicaoNegocio : BaseBusinessLogic
    {
        #region Atributos

        private int _erroFalhaNaGravacao = 109796;
        private int _erroUsuarioSemPermissao = 109711;
        
        private ResourceAccess.DistribuicaoNegocio resource;        

        #endregion

        #region Propriedades

        public int ErroFalhaNaGravacao
        {
            get { return _erroFalhaNaGravacao; }
            set { _erroFalhaNaGravacao = value; }
        }

        public int ErroUsuarioSemPermissao
        {
            get { return _erroUsuarioSemPermissao; }
            set { _erroUsuarioSemPermissao = value; }
        }

        #endregion

        #region Construtor
        public DistribuicaoNegocio()
        {
            resource = new Sinacor.Servico.Bovespa.Alocacao.ResourceAccess.DistribuicaoNegocio();
        }
        #endregion

        #region Metodos
        /// <summary>
        /// Pesquisa negocios distribuidos
        /// </summary>
        /// <param name="filtro"></param>
        public List<BusinessEntity.NegocioDistribuido> ConsultarNegociosDistribuidos(BusinessEntity.Parameter.FiltroNegocioDistribuicao filtro)
        {
            BusinessRulesValidator validador = new BusinessRulesValidator();
            BusinessRuleValidation.CamposObrigatoriosFiltroNegocioDistribuicao val = new Sinacor.Servico.Bovespa.Alocacao.BusinessLogic.BusinessRuleValidation.CamposObrigatoriosFiltroNegocioDistribuicao();
            val.EntityToValidate = filtro;
            validador.AddValidation("CamposObrigatorios", val);
            validador.Validate();

            return resource.ConsultarNegociosDistribuidos(filtro);
        }

        /// <summary>
        /// Pesquisa negocios casados e nao distribuidos
        /// </summary>
        /// <param name="filtro"></param>
        public List<BusinessEntity.NegocioNaoDistribuido> ConsultarNegociosNaoDistribuidos(BusinessEntity.Parameter.FiltroNegocioDistribuicao filtro)
        {
            BusinessRulesValidator validador = new BusinessRulesValidator();
            BusinessRuleValidation.CamposObrigatoriosFiltroNegocioDistribuicao val = new Sinacor.Servico.Bovespa.Alocacao.BusinessLogic.BusinessRuleValidation.CamposObrigatoriosFiltroNegocioDistribuicao();
            val.EntityToValidate = filtro;
            validador.AddValidation("CamposObrigatorios", val);
            validador.Validate();

            return resource.ConsultarNegociosNaoDistribuidos(filtro);
        }

        /// <summary>
        /// Distribui os negocios
        /// </summary>
        /// <param name="negociosDistribuidos"></param>
        public List<BusinessEntity.DadosDistribuicao> DistribuirNegocio(BusinessEntity.NegociosDistribuidos negociosDistribuidos)
        {
            ResourceAccess.DistribuicaoNegocio resourceAccess = new Sinacor.Servico.Bovespa.Alocacao.ResourceAccess.DistribuicaoNegocio();

            BusinessEntity.Resultado result = new Sinacor.Servico.Bovespa.Alocacao.BusinessEntity.Resultado();

            this.ValidarDistribuicao(negociosDistribuidos);

            if (negociosDistribuidos.Digitados.TrueForAll(x => x.Error == null))
            {
                result = resourceAccess.LimparVariaveis();
                if (!result.Sucesso)
                {
                    this.TratarExcecoes(result);
                }

                foreach (NegocioNaoDistribuido item in negociosDistribuidos.Negocios)
                {
                    result = resourceAccess.CarregarNegocioNaoDistribuido(item);
                    if (!result.Sucesso)
                    {
                        this.TratarExcecoes(result);
                    }
                }

                foreach (DadosDistribuicao item in negociosDistribuidos.Digitados)
                {
                    result = resourceAccess.CarregarDigitacao(item);
                    if (!result.Sucesso)
                    {
                        this.TratarExcecoes(result);
                    }
                }

                result = resourceAccess.CarregarIdDistribuicao(resourceAccess.GerarIdDistribuicao());
                if (!result.Sucesso)
                {
                    this.TratarExcecoes(result);
                }

                result = resourceAccess.ExecutarDistribuicao();
                if (!result.Sucesso)
                {
                    this.TratarExcecoes(result);
                }
            }

            return negociosDistribuidos.Digitados;
        }

        /// <summary>
        /// Trata a excecao gerada na execucao de uma procedure ou function oracle
        /// </summary>
        /// <param name="entity"></param>
        private void TratarExcecoes(BusinessEntity.Resultado entity)
        {
            if (entity.CodigoErro == -1)
            {
                throw new BusinessException(ErroFalhaNaGravacao);
            }
            else
            {
                if (string.IsNullOrEmpty(entity.Argumentos))
                {
                    throw new BusinessException(entity.CodigoErro);
                }
                else
                {
                    List<object> ret = Sinacor.Infra.Service.ExceptionHandling.ErrorMessage.ConvertXmlArgumentsToParameters(entity.Argumentos);
                }
            }
        }

        /// <summary>
        /// Valida todas as linhas digitadas
        /// </summary>
        /// <param name="negociosDistribuidos"></param>
        public List<BusinessEntity.DadosDistribuicao> ValidarDistribuicao(BusinessEntity.NegociosDistribuidos negociosDistribuidos)
        {
            Movimento.BusinessLogic.ControleMovimentoOrdens movimento = new Movimento.BusinessLogic.ControleMovimentoOrdens();
            Movimento.BusinessEntity.DataMovimento data = new Movimento.BusinessEntity.DataMovimento();
            Movimento.BusinessEntity.InformacoesMovimento info = new Movimento.BusinessEntity.InformacoesMovimento();

            info = movimento.ObterInformacoesMovimento(data);
            if (info.EstadoMovimento == Sinacor.Servico.Bovespa.Movimento.BusinessEntity.Enum.TipoMovimento.Aberto)
            {
                if (AuthorizationContext.Current.CheckUserAccess("DISNEG", "ORD"))
                {
                    foreach (BusinessEntity.DadosDistribuicao digitado in negociosDistribuidos.Digitados)
                    {
                        negociosDistribuidos.DigitadoAtual = digitado;
                        this.ValidarDistribuicaoDigitadoAtual(negociosDistribuidos);
                    }

                    if (negociosDistribuidos.Digitados.TrueForAll(x => x.Error == null))
                    {
                        var faixaQuantidadePrecoPercentualDistribuir = new BusinessRuleValidation.FaixaQuantidadePrecoPercentualDistribuir();
                        faixaQuantidadePrecoPercentualDistribuir.EntityToValidate = negociosDistribuidos;

                        BusinessRulesValidator validador = new BusinessRulesValidator();
                        validador.AddValidation("FaixaQuantidadePrecoPercentualDistribuir", faixaQuantidadePrecoPercentualDistribuir);
                        validador.IsAllValid();
                    }
                }
                else
                {
                    throw new BusinessException(ErroUsuarioSemPermissao);
                }
            }
            else
            {
                throw new BusinessException(ErroUsuarioSemPermissao);
            }

            return negociosDistribuidos.Digitados;
        }

        /// <summary>
        /// Valida a linha digitada atual
        /// </summary>
        /// <param name="negociosDistribuidos"></param>
        public BusinessEntity.DadosDistribuicao ValidarDistribuicaoDigitadoAtual(BusinessEntity.NegociosDistribuidos negociosDistribuidos)
        {
            try
            {
                BusinessEntity.NegocioDistribuido negocioDistribuido = new BusinessEntity.NegocioDistribuido()
                {
                    DadosAlocacao = negociosDistribuidos.DigitadoAtual,
                    Negocio = new BusinessEntity.NegocioNaoDistribuido
                    {
                        Mercado = (ManutencaoOrdens.BusinessEntity.Enum.TipoMercado)negociosDistribuidos.DigitadoAtual.Mercado,
                        NaturezaOperacao = negociosDistribuidos.Negocios[0].NaturezaOperacao,
                        Codigo = negociosDistribuidos.DigitadoAtual.CodigoNegocio,
                        DataPregao = negociosDistribuidos.Negocios[0].DataPregao,
                        Bolsa = negociosDistribuidos.Negocios[0].Bolsa,
                    }
                };

                // Verificar se a digitacao do direcionado está bloqueada
                int retorno = (from d in negociosDistribuidos.Negocios
                               where (d.Mercado != ManutencaoOrdens.BusinessEntity.Enum.TipoMercado.Vista) &&
                                     (d.Mercado != ManutencaoOrdens.BusinessEntity.Enum.TipoMercado.Fracionario) &&
                                     (d.Mercado != ManutencaoOrdens.BusinessEntity.Enum.TipoMercado.Futuro)
                               select d).Count();

                // Se estiver bloqueada ou usuario não digitou nada, completar
                if (retorno == 0 ||
                    negociosDistribuidos.DigitadoAtual.Direcionado == null ||
                    (negociosDistribuidos.DigitadoAtual.Direcionado.Cliente == null ||
                    negociosDistribuidos.DigitadoAtual.Direcionado.DigitoVerificadorCliente == null ||
                    negociosDistribuidos.DigitadoAtual.Direcionado.Usuario == null))
                {
                    BusinessLogic.AlocacaoDireta bl = new AlocacaoDireta();
                    var direcionado = bl.ObterDirecionado(negocioDistribuido);

                    if (direcionado != null)
                    {
                        negociosDistribuidos.DigitadoAtual.Direcionado.Cliente = direcionado.Cliente;
                        negociosDistribuidos.DigitadoAtual.Direcionado.DigitoVerificadorCliente = direcionado.DigitoVerificadorCliente;
                        negociosDistribuidos.DigitadoAtual.Direcionado.Usuario = direcionado.Usuario;
                    }
                }

                BusinessRulesValidator validador = new BusinessRulesValidator();
                validador.StopOnFirstValidationError = true;

                BusinessRuleValidation.ExisteNegocioDistribuir existe = new Sinacor.Servico.Bovespa.Alocacao.BusinessLogic.BusinessRuleValidation.ExisteNegocioDistribuir();
                existe.EntityToValidate = negociosDistribuidos;
                validador.AddValidation("ExisteNegocioDistribuir", existe);

                BusinessRuleValidation.GrupoAssessoresStatusCliente grupoAssessoresStatusCliente = new Sinacor.Servico.Bovespa.Alocacao.BusinessLogic.BusinessRuleValidation.GrupoAssessoresStatusCliente();
                grupoAssessoresStatusCliente.EntityToValidate = negocioDistribuido;
                validador.AddValidation("GrupoAssessoresStatusCliente", grupoAssessoresStatusCliente);

                BusinessRuleValidation.BloqueioCliente bloqueioCliente = new Sinacor.Servico.Bovespa.Alocacao.BusinessLogic.BusinessRuleValidation.BloqueioCliente();
                bloqueioCliente.EntityToValidate = negocioDistribuido;
                validador.AddValidation("BloqueioCliente", bloqueioCliente);

                BusinessRuleValidation.DigitoVerificadorCliente digitoVerificadorCliente = new Sinacor.Servico.Bovespa.Alocacao.BusinessLogic.BusinessRuleValidation.DigitoVerificadorCliente();
                digitoVerificadorCliente.EntityToValidate = negocioDistribuido;
                validador.AddValidation("DigitoVerificadorCliente", digitoVerificadorCliente);
                
                BusinessRuleValidation.OrdemCliente ordemCliente = new Sinacor.Servico.Bovespa.Alocacao.BusinessLogic.BusinessRuleValidation.OrdemCliente();
                ordemCliente.EntityToValidate = negociosDistribuidos;
                validador.AddValidation("OrdemCliente", ordemCliente);

                BusinessRuleValidation.ExisteCarteira existeCarteira = new Sinacor.Servico.Bovespa.Alocacao.BusinessLogic.BusinessRuleValidation.ExisteCarteira();
                existeCarteira.EntityToValidate = negocioDistribuido;
                validador.AddValidation("ExisteCarteira", existeCarteira);

                BusinessRuleValidation.CamposObrigatoriosNegocioAlocadoDireto val = new Sinacor.Servico.Bovespa.Alocacao.BusinessLogic.BusinessRuleValidation.CamposObrigatoriosNegocioAlocadoDireto();
                val.EntityToValidate = negocioDistribuido;
                validador.AddValidation("CamposObrigatorios", val);

                BusinessRuleValidation.FaixaPercentualReducaoAcrescimo faixaPercentualReducaoAcrescimo = new Sinacor.Servico.Bovespa.Alocacao.BusinessLogic.BusinessRuleValidation.FaixaPercentualReducaoAcrescimo();
                faixaPercentualReducaoAcrescimo.EntityToValidate = negocioDistribuido;
                validador.AddValidation("FaixaPercentualReducaoAcrescimo", faixaPercentualReducaoAcrescimo);

                validador.Validate();
            }
            catch (Exception ex)
            {
                var busEx = ex as BusinessException;
                var valEx = ex as ValidationException;

                if (busEx != null)
                    negociosDistribuidos.DigitadoAtual.AddError(busEx.ErrorNumber, busEx.Parameters.ToArray());
                else if (valEx != null)
                    negociosDistribuidos.DigitadoAtual.AddError(valEx.ValidationErrors);
                else
                    throw ex;
            }

            return negociosDistribuidos.DigitadoAtual;
        }

        #endregion
    }
}